#include "numuCCPXAnalysis.hxx"
#include "CategoriesUtils.hxx"


numuCCPXAnalysis::numuCCPXAnalysis(AnalysisAlgorithm* ana) : baseAnalysis(ana) 
{
  // Minimum accum level to save event into the output tree
  SetMinAccumCutLevelToSave(ND::params().GetParameterI("numuCCPXAnalysis.MinAccumLevelToSave"));

  // Create a numuCCAnalysis passing this analysis to the constructor. In that way the same managers are used
  _numuCCAnalysis = new numuCCAnalysis(this);

  //use it when new version of highland2 is available
  //UseAnalysis(_numuCCAnalysis);

  // Add track categories for the proton candidate
  ND::categ().AddStandardCategories("Proton");
  ND::categ().AddStandardCategories("X");

  // Add the package version
  ND::versioning().AddPackage("numuCCPXAnalysis", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("NUMUCCPXANALYSISROOT")));
}


void numuCCPXAnalysis::DefineSelections()
{
  sel().AddSelection("kTrackerNumuCCPX", "inclusive numuCCPX selection",  new numuCCPXSelection(1));
}

bool numuCCPXAnalysis::Process()
{
  //------ This function is called for each bunch and each toy experiment  ----------
  bool passed = sel().GetSelection("kTrackerNumuCCPX")->Apply(*_event,*_ccPX_box); 

  return passed;
}
                                        
void numuCCPXAnalysis::DefineMicroTrees(bool addBase)
{
  // -------- Add variables to the analysis tree ----------------------

  // Variables from the numuCCAnalysis analysis (including the ones in baseAnalysis by default, otherwise addBase should be false
  if (addBase) _numuCCAnalysis->DefineMicroTrees(addBase);

  AddVarI(output(),ntrackertracks,"");

  AddVarI(output(),eventtypesim,"");
  AddVarI(output(),simotherpdg,"");

  AddVarI(output(),necaltracks,"");
  AddVarI(output(),ecalpdgsim,"");

//selp
  AddVarF(   output(), selp_truemom, "");
  AddVar4VF( output(), selp_truedir, ""); 
  AddVarI(   output(), selp_pdg,"");
  AddToyVarI(output(), selp_NDOF,      "");
  AddToyVarF(output(), selp_Chi2,      "");
  AddToyVarF(output(), selp_mom,      "");
  AddVar3VF( output(), selp_dir, "");
  AddVarVI(  output(), selp_tpc_nhits,        "", selp_ntpcs);
  AddVar4VF( output(), selp_endpos, "");
//selX
  AddVarF(   output(), selX_truemom, "");
  AddVar4VF( output(), selX_truedir, ""); 
  AddVarI(   output(), selX_pdg,"");
  AddToyVarI(output(), selX_NDOF,      "");
  AddToyVarF(output(), selX_Chi2,      "");
  AddToyVarF(output(), selX_mom,      "");
  AddVar3VF( output(), selX_dir, "");
  AddVarVI(  output(), selX_tpc_nhits,        "", selX_ntpcs);
  AddVar4VF( output(), selX_endpos, "");

  AddVarI(   output(), selX_charge,"");
  AddVarI(   output(), selX_PID,"");
}

void numuCCPXAnalysis::FillParticle(ccpxvar truemom, ccpxvar truedir, ccpxvar pdg, ccpxvar tpc_nhits, ccpxvar endpos, ccpxvar dir, ccpxvar mom, ccpxvar NDOF, ccpxvar Chi2, AnaTrackB* tmppar)
{
  //true variables
  if(tmppar->TrueTrack ) {
    output().FillVar(truemom,                    tmppar->TrueTrack->Momentum);       
    output().FillVectorVarFromArray(truedir,     tmppar->TrueTrack->Direction,   3);       
    output().FillVar(pdg,                        tmppar->TrueTrack->PDG);
  }
  
  for(Int_t subdet = 0; subdet<3; subdet++) {
    if (!SubDetId::GetDetectorUsed(tmppar->Detector, static_cast<SubDetId::SubDetEnum >(subdet+2))) continue;
    AnaTpcTrack* TPCSegment = static_cast<AnaTpcTrack*>(anaUtils::GetSegmentInDet( *tmppar,static_cast<SubDetId::SubDetEnum >(subdet+2)));
    if (!TPCSegment) continue;
    
    output().FillVectorVar(tpc_nhits,   TPCSegment->NHits);
    //important to have this:
    output().IncrementCounterForVar(tpc_nhits);
  }
  
  //basic kinematic variables that wont be changed by systematics propagation
  output().FillVectorVarFromArray(endpos, tmppar->PositionEnd, 4);
  output().FillVectorVarFromArray(dir,    tmppar->DirectionStart, 3);

  AnaTrack* track = static_cast<AnaTrack*>(tmppar);
  output().FillToyVar(mom,  track->Momentum);
  output().FillToyVar(NDOF, track->NDOF);
  output().FillToyVar(Chi2, track->Chi2);
}

void numuCCPXAnalysis::FillMicroTrees(bool addBase)
{
  // Fill variables from numuCCAnalysis
  if (addBase) _numuCCAnalysis->FillMicroTrees(addBase);

  const Int_t ntts = box().TrackerTracks.size();
  output().FillVar(ntrackertracks, ntts);

  output().FillVar(eventtypesim, box().EventTypeSim);
  output().FillVar(simotherpdg, box().SimOtherPDG);

  output().FillVar(necaltracks, box().NECalTracks);
  output().FillVar(ecalpdgsim, box().ECalPDGSim);

  AnaTrackB* tmpp = box().ProtonCandidate;
  FillParticle(selp_truemom, selp_truedir, selp_pdg, selp_tpc_nhits, selp_endpos, selp_dir, selp_mom, selp_NDOF, selp_Chi2, tmpp);

  AnaTrackB* tmpx = box().XCandidate;
  if(tmpx){
    FillParticle(selX_truemom, selX_truedir, selX_pdg, selX_tpc_nhits, selX_endpos, selX_dir, selX_mom, selX_NDOF, selX_Chi2, tmpx);
    output().FillVar(selX_charge, box().XCharge);
    output().FillVar(selX_PID, box().XPID);
  }
}

//========================================================================================
//========================================================================================
void numuCCPXAnalysis::InitializeConfiguration()
{
  // Use the same event for the numuCCAnalysis
  _numuCCAnalysis->SetEvent(_event);
  _numuCCAnalysis->InitializeConfiguration();
}

void numuCCPXAnalysis::DefineConfigurations()
{
  // Same configurations as for numuCC
  _numuCCAnalysis->DefineConfigurations();
}

void numuCCPXAnalysis::DefineCorrections()
{
  _numuCCAnalysis->DefineCorrections();
}

void numuCCPXAnalysis::DefineSystematics()
{
  _numuCCAnalysis->DefineSystematics();
}

void numuCCPXAnalysis::DefineTruthTree()
{
  // Variables from baseAnalysis (run, event, ...)
  _numuCCAnalysis->DefineTruthTree();
}

void numuCCPXAnalysis::FillTruthTree(const AnaTrueVertex& vtx)
{
  // Fill the numuCC variables
  //enabling it makes the file output size smaller!!
  _numuCCAnalysis->FillTruthTree(vtx);
}

bool numuCCPXAnalysis::CheckFillTruthTree(const AnaTrueVertex& vtx)
{
  return _numuCCAnalysis->CheckFillTruthTree(vtx);
}

bool numuCCPXAnalysis::CheckFillRooTracker(const AnaTrueVertex& vtx)
{
  return _numuCCAnalysis->CheckFillRooTracker(vtx);
}
                                     
void numuCCPXAnalysis::InitializeToy()
{
  // Delete the box and create a new one
  if (_ccPX_box) delete _ccPX_box;
  _ccPX_box = new AnaBoxCCPX();

  // Use the same box for the numuCCAnalysis
  _numuCCAnalysis->SetBox(_ccPX_box);

  // Use the same event for the numuCCAnalysis
  _numuCCAnalysis->SetEvent(_event);
}

void numuCCPXAnalysis::FillToyVarsInMicroTrees(bool addBase)
{
  // Variables from the numuCCAnalysis analysis (including the ones in baseAnalysis by default, otherwise addBase should be false
  if (addBase) _numuCCAnalysis->FillToyVarsInMicroTrees(addBase);
}
                                                                                                                           
void numuCCPXAnalysis::FinalizeToy()
{
  _numuCCAnalysis->FinalizeToy();
}

void numuCCPXAnalysis::FillCategories()
{
  anaUtils::FillCategories(_event, static_cast<AnaTrack*>(box().MuonCandidate),"");

  // for the proton candidate                                                                                                                                                                               
  anaUtils::FillCategories(_event, static_cast<AnaTrack*>(box().ProtonCandidate),"Proton");

  anaUtils::FillCategories(_event, static_cast<AnaTrack*>(box().XCandidate),"X");
}

